home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / tjgold.zip / INSTALL.004 / FGUSER14.TXT < prev    next >
Text File  |  1995-05-29  |  47KB  |  1,147 lines

  1.                           Displaying Lists in Windows
  2.  
  3.                                        "He shall live and unto him shall
  4.                                         be given of the gold of Arabia."
  5.                                                       1662 Prayer Book
  6.  
  7. Introduction
  8.  
  9.           List, list, lists. Our lives and our software are often
  10.      dominated by lists. Gold provides a family of flexible tools to
  11.      help you manage software lists. (Your lives are your own
  12.      responsibility!)
  13.  
  14.           In the last chapter you learned how data can be stored in
  15.      single and double linked lists. In this chapter you will learn how
  16.      the data in linked lists, as well as data stored in arrays and
  17.      databases, can be displayed in list windows.
  18.  
  19.      Gold provides the following three categories of list window:
  20.  
  21.           Category            Description
  22.           Quick List Windows  Many applications just want to pop-up a
  23.                               simple (single column) list window and
  24.                               allow the user to select one item. Gold
  25.                               provides a simple but not very
  26.                               customizable function RunListStrLL for
  27.                               displaying quick and dirty lists.
  28.           Browse Windows      As the name suggests, a browse window is
  29.                               for browsing the contents of a list.
  30.                               Unlike the other list catagories, a browse
  31.                               window does not have a highlight bar --
  32.                               there is no notion of a selected line or
  33.                               item. The window can be scrolled
  34.                               vertically and horizontally. Browse
  35.                               windows are ideal for displaying file
  36.                               contents, help text and the like.
  37.           List Windows        List windows display data in single or
  38.                               multiple columns, and one item in the list
  39.                               is always highlighted, i.e. selected.The
  40.                               user can (if the application permits it)
  41.                               tag multiple items in the list. These
  42.                               lists are ideal for displaying filenames,
  43.                               or any list where the user needs to select
  44.                               one (or more) items.
  45.           Grid Windows        A grid window is similar to a list window
  46.                               in as much as the user is presented with a
  47.                               list and one item in the list is always
  48.                               highlighted. A grid window is designed,
  49.                               however, to provide a table or columnar
  50.                               view of a record similar to the table
  51.                               views in Paradox. A user can scroll right
  52.                               and left one column at a time (as opposed
  53.                               to one character at a time).
  54.  
  55.  
  56.           In addition to providing list windows, Gold supports all these
  57.      list types in user input forms, i.e. you can have a field on a form
  58.      which is a browser, list or grid. These features are discussed in
  59.      Chapter 16.
  60.  
  61. Quick and Dirty List Windows
  62.  
  63.           In the remainder of this chapter you will learn how to use the
  64.      RunBrowse, RunList and RunGrid procedures to create flexible
  65.      windows with a myriad of options. Before you explore these
  66.      inticacies, you might want to consider using RunListStrLL (defined
  67.      below) for your simple list windows.
  68.  
  69.      RunListStrLL(ListSource:StringLL;Tit:StrScreen):longint;
  70.  
  71.           Displays the contents of a stringLL in a list window. The
  72.      function returns the number of the highlighted pick, or zero if the
  73.      user escapes.
  74.  
  75.           This function uses the ListVars variables WX1, WY1, WX2, WY2
  76.      and WStyle to determine the window coordinates. Sets these
  77.      variables to appropriate values if the default window size is too
  78.      large.
  79.  
  80.      Run the demo file DEMLIS5.PAS to see RunListStrLL in action.
  81.  
  82. Building a Flexible List Window -- A Crash Course
  83.  
  84.           No matter which type of list you are displaying, Gold needs to
  85.      know the main properties of the data and the characteristics of the
  86.      window in which the data will be displayed. For example, before a
  87.      list window can be displayed, Gold needs to know some of the
  88.      following information:
  89.  
  90.           What type of data is to be displayed, e.g. a single linked
  91.      list, double linked list, array, etc.
  92.  
  93.           Where the data is stored, i.e. the name of the variable.
  94.           The dimensions and style of the window.
  95.           The window title.
  96.           Any optional list headers and footers.
  97.           What colors are to be used.
  98.           Can the user tag more than one item.
  99.           .... you get the idea.
  100.  
  101.           You define all these list characteristics by creating a
  102.      variable (of type ListCfg, for list configuration), initializing
  103.      the variable, and then setting various components of the variable
  104.      to define your specific needs.
  105.  
  106.           In other words, to display a list in a window you need at
  107.      least two variables: a list configuration variable, and a variable
  108.      used to store the data.
  109.  
  110.           The following code (extracted from the demo file DEMLS1.PAS)
  111.      shows a minimalist application which displays the contents of
  112.      SingleLL in a list window:
  113.  
  114.           var
  115.              Properties: ListCfg;
  116.              GirlFriends: SingleLL;
  117.              RetCode: integer;
  118.  
  119.           procedure BuildTheList;
  120.           {}
  121.           begin
  122.              InitSLLStr(GirlFriends);
  123.              SLLSetActiveList(GirlFriends);
  124.              Retcode := SLLAddStr('Erica');
  125.              inc(Retcode,SLLAddStr('Theresa'));
  126.              inc(Retcode,SLLAddStr('Lynn'));
  127.              inc(Retcode,SLLAddStr('Donna'));
  128.              inc(Retcode,SLLAddStr('Godzilla'));
  129.           end; { BuildTheList }
  130.  
  131.           procedure SetScreen;
  132.           {Paints the background}
  133.           begin
  134.              Clear(WhiteOnBlack,'°');
  135.              ClearLine(1,YellowOnBlue);
  136.              WriteCenter(1,UseTint,' A Simple List Window ');
  137.              GotoXY(1,1);
  138.           end; {SetScreen}
  139.  
  140.           begin
  141.              BuildTheList;
  142.              SetScreen;
  143.              if RetCode <> 0 then
  144.                 PromptOK(' Error ','Unable to build the list')
  145.              else
  146.              begin
  147.                 InitListCfg(Properties);
  148.                 ListAssignSLL(Properties,Girlfriends);
  149.                 MouseShow(true);
  150.                 RunList(Properties,' My first list! ');
  151.                 MouseShow(false);
  152.              end;
  153.              SLLSetActiveList(GirlFriends);
  154.              SLLDestroy;
  155.           end. { DEMLS1 }
  156.  
  157.           In this example, the list configuration variable is named
  158.      Properties, and the data is stored in a single linked list named
  159.      Girlfriends. (If you are not familiar with linked lists, read the
  160.      previous chapter before proceeding.)
  161.  
  162.           Apart from the code to paint the screen and populate the
  163.      linked list, the list window can be displayed in just three lines
  164.      of code:
  165.  
  166.      InitListCfg(Properties);
  167.  
  168.           Uses InitListCfg to initialize the Properties variable to
  169.      default values.
  170.  
  171.      ListAssignSLL(Properties,Girlfriends);
  172.  
  173.           Uses ListAssignSLL to advise Properties of the data type
  174.      (SingleLL) and location (the address of the variable Girlfriends)
  175.      of the list data.
  176.  
  177.      RunList(Properties,' My first list! ');
  178.  
  179.      Calls RunList to display the list in a window.
  180.  
  181.           If you run DEMOLS1.PAS you will see that Gold creates a large
  182.      list window. Since we didn't define any of the window properties,
  183.      apart from the window title (in the call to RunList), Gold used
  184.      some defaults.
  185.  
  186.           You can refine the list window in many ways. The following
  187.      code fragment is an extract from DEMLS2.PAS which is the same code
  188.      base as DEMLS1.PAS except that the window is customized to better
  189.      fit the list of girlfriends!
  190.  
  191.           ListSetWin(Properties,25,5,55,11,1);
  192.  
  193. Defining the List Configuration
  194.  
  195.           The key to displaying list/browse/grid windows is to declare a
  196.      variable of type ListCfg, and then call Gold functions to set
  197.      ListCfg to meet your specific needs.
  198.  
  199. Initializing ListCfg
  200.  
  201.           Always, always, always call InitListCfg to initialize the
  202.      ListCfg variable before calling the other list procedures and
  203.      functions.
  204.  
  205.      InitListCFG(var ListDetails: ListCfg);
  206.  
  207.      Initializes a list configuration variable.
  208.  
  209. Assigning the Data Source
  210.  
  211.           Having initialized the ListCfg variable (I promise I won't
  212.      repeat the fact that it must be initialized) you then need to
  213.      update the variable with information about the list data source.
  214.      Gold can display the contents of a SingleLL, DoubleLL, array or a
  215.      custom data source where you supply a function to feed the list
  216.      engine with the necessary strings. Depending on your data source,
  217.      you would call one of the following procedures to update the
  218.      ListCfg variable with the data source details:
  219.  
  220.      ListAssignSLL(var ListDetails: ListCfg; var TheList:SingleLL);
  221.  
  222.           Sets the ListCfg variable data source as a single linked list
  223.      stored in the variable TheList.
  224.  
  225.      ListAssignDLL(var ListDetails: ListCfg; var TheList:DoubleLL);
  226.  
  227.           Sets the ListCfg variable data source as a double linked list
  228.      stored in the variable TheList.
  229.  
  230.      ListAssignArray(var ListDetails: ListCfg; var ListSource;
  231.                          StrLen:Byte;ArrayElements:byte);
  232.  
  233.           Sets the ListCfg variable data source as a string array stored
  234.      in the variable ListSource. The last two parameters define the
  235.      length of each string in the array, and the number of elements in
  236.      the array, respectively.
  237.  
  238.           The ListAssignCustom procedure is discussed later in the
  239.      section Using a Custom Data Source.
  240.  
  241. Setting Window Properties
  242.  
  243.           When the ListCfg variable is initialized, the window
  244.      properties (such as the window position and dimensions) are set to
  245.      some standard defaults. If these defaults are not appropriate, you
  246.      can customize them with the following two procedures:
  247.  
  248.      ListSetWin(var ListDetails: ListCfg; X1,Y1,X2,Y2:integer;
  249.                                               Style:byte);
  250.  
  251.           Defines the upper left and lower right corners of the window
  252.      along with the window style. (Refer to Chapter 4 for a discussion
  253.      of window styles.)
  254.  
  255.      ListSetGaps(var ListDetails:ListCfg;LeftGap,RightGap,
  256.                                              BotGap,TopGap: byte);
  257.  
  258.           This procedure allows you to set the gap or whitespace area
  259.      around the list body. The list/browse/grid data does not need to
  260.      fill the entire window.
  261.  
  262.  
  263.           If you want to change the window defaults, update the
  264.      following variables: ListVars.X1, ListVars.Y1, ListVars.X2,
  265.      ListVars.Y2, and ListVars.WinStyle.
  266.  
  267. Multi-Column Lists
  268.  
  269.           A list window displayed with RunList (but not RunBrowse or
  270.      RunGrid) can display a list in multiple columns. By default, a list
  271.      is displayed in a single column that is the width of the window,
  272.      but the following function can be used to change the default column
  273.      width to a fixed value:
  274.  
  275.      ListSetColWidth(var ListDetails: ListCfg; Width: byte);
  276.  
  277.           Specifies the width of each column in the list (when the list
  278.      is displayed with RunList).
  279.  
  280.           If the column width is set to zero, or the specified column
  281.      width is wider than the window, Gold will display the list in a
  282.      single column.
  283.  
  284. Setting the Window Colors
  285.  
  286.           As always, the default colors are defined in the TINT
  287.      structure, and the following elements pertain to list windows:
  288.  
  289.           ListHi1
  290.           ListHi2
  291.           ListNorm1
  292.           ListNorm2
  293.           ListMarkers
  294.           ListScrollbarHi
  295.           ListScrollbarNorm
  296.           ListBorder1
  297.           ListBorder2
  298.           ListBorderOff
  299.           ListTitle
  300.           ListHeaders
  301.           ListIcons
  302.  
  303.           You can modify the defaults (used by any new list windows
  304.      initialized after the modification) by using the standard
  305.      GoldSetColor procedure.
  306.  
  307.           You can modify the colors of a specific list window by using
  308.      the following function:
  309.  
  310.      ListSetColor(var ListDetails: ListCfg; A:TintElement; C:byte);
  311.  
  312.      Sets the color of one of the elements of a list window.
  313.  
  314.           The following code is an extract from DEMLS3.PAS which
  315.      customizes the list display colors:
  316.  
  317.           procedure CustomizeColors;
  318.           {}
  319.           begin
  320.              ListSetColor(Prop,ListHi1,BlackonGreen);
  321.              ListSetColor(Prop,ListHi2,YellowOnGreen);
  322.              ListSetColor(Prop,ListNorm1,YellowOnMagenta);
  323.              ListSetColor(Prop,ListNorm2,WhiteOnMagenta);
  324.              ListSetColor(Prop,ListMarkers,LightgrayonMagenta);
  325.              ListSetColor(Prop,ListScrollbarHi,WhiteOnMagenta);
  326.              ListSetColor(Prop,ListScrollbarNorm,WhiteOnMagenta);
  327.              ListSetColor(Prop,ListBorder1,YellowOnMagenta);
  328.              ListSetColor(Prop,ListBorder2,YellowOnMagenta);
  329.              ListSetColor(Prop,ListBorderOff,BlackOnMagenta);
  330.              ListSetColor(Prop,ListTitle,WhiteOnMagenta);
  331.              ListSetColor(Prop,ListHeaders,GreenOnMagenta);
  332.              ListSetColor(Prop,ListIcons,LightCyanOnMagenta);
  333.           end; { CustomizeColors }
  334.  
  335. Controlling Item Tagging
  336.  
  337.           List and grid windows (but not browse windows) support item
  338.      tagging whereby a user can select or tag more than one item in a
  339.      list. You might use this for marking items in a database to print,
  340.      or tag files to be deleted, etc.
  341.  
  342.           Tagging is only supported in lists that have a data source of
  343.      SingleLL or DoubleLL.
  344.  
  345.           By default a list does not support tagging. However, you can
  346.      use the following procedure to control tagging:
  347.  
  348.      ListSetTagging(var ListDetails: ListCfg; On:boolean);
  349.  
  350.           Sets the taggability state of a list or grid. Pass a TRUE to
  351.      allow tagging and a FALSE to disable it.
  352.  
  353.           When an item is tagged, Gold accesses the appropriate node of
  354.      the list and updates one of the bit flags. The Gold constant TagBit
  355.      identifies the bit flag that is set when the item is tagged.
  356.  
  357.           When the user has completed the tagging operation, you can use
  358.      the function SLLGetBit or DLLGetBit to test the bit status of each
  359.      item in the list.
  360.  
  361.           The demo file DEMLS4.PAS displays a list of taggable files in
  362.      a multiple column window. The following code fragment is extracted
  363.      from DEMLS4.PAS and shows how to test whether the items in the list
  364.      are tagged:
  365.  
  366.            for I := 1 to Properties.TotalNodes do
  367.            begin
  368.               if DLLGetBit(DLLNodePtr(I),TagBit) then
  369.               begin
  370.                  writeln(DLLGetStr(I));
  371.                  inc(Counter);
  372.               end;
  373.            end;
  374.  
  375.  
  376.           Notice that the ListCfg element TotalNodes is used to
  377.      determine how many nodes were displayed in the list window, i.e.
  378.      Properties.TotalNodes.
  379.  
  380.  
  381. Dual Colored Lists
  382.  
  383.           SingleLL- and DoubleLL-based lists support dual colored lists,
  384.      i.e. some items are displayed in one color and other items are
  385.      displayed in a different color. To enable dual colored lists, use
  386.      the following function:
  387.  
  388.      ListSetTwoColors(var ListDetails: ListCfg; On:boolean);
  389.  
  390.           Pass TRUE to enable two colored lists, or FALSE for single
  391.      colored lists.
  392.  
  393.           Having enabled the two colors, you need to mark those items in
  394.      the list that you want displayed in the secondary color. Gold
  395.      checks the bit named ColBit at the node to decide which color set
  396.      to use. To force a node to be displayed in a secondary color, you
  397.      need to set the ColBit on.
  398.  
  399.           The following code is an extract from DEMBR4.PAS which
  400.      displays lines that contain the words procedure and function in the
  401.      secondary color.
  402.  
  403.           NodePtr := DLL.StartNodePtr;
  404.           while NodePtr <> nil do
  405.           begin
  406.              TempStr := DLLGetNodeStr(NodePtr,0,0);
  407.              if CaseSens then
  408.                 P := pos(Str,TempStr)
  409.              else
  410.                 P := pos(SetUpper(Str),SetUpper(TempStr));
  411.              if P > 0 then
  412.                 DLLSetBit(NodePtr,Colbit,true);
  413.              NodePtr := NodePtr^.NextPtr;
  414.           end;
  415.  
  416.           If you want to synchronize the tag and color features so that
  417.      all tagged items appear in a different color, Gold will do the work
  418.      for you. All you have to do is use the following procedure:
  419.  
  420.      ListSetTagColor(var ListDetails: ListCfg; On:boolean);
  421.  
  422.           Pass TRUE to have tagged items appear in the secondary color,
  423.      or FALSE to have tagged and untagged items appear in the same
  424.      color.
  425.  
  426. Using Headers and Footers
  427.  
  428.           All three list window types (browse, list and grid) support
  429.      multi-line headers and footers. Out of the box, Gold limits the
  430.      number of heading lines and footer lines to 4, but you can change
  431.      the number by assigning a different value to the constants
  432.      ListMaxHeaders and ListMaxFooters declared in GOLDLIST.
  433.  
  434.           To minimize memory usage, all headers and footers must be
  435.      stored as string variables in your program. (Gold simply stores a
  436.      pointer to the variable.)
  437.  
  438.           The following six procedures can be used to manage the headers
  439.      and footers:
  440.  
  441.      ListAssignHeader(var ListDetails: ListCfg; Line:byte; var
  442.                                                        Heading:string);
  443.  
  444.           Sets the list configuration variable to display a string as a
  445.      header. A string variable must be passed -- a string literal will
  446.      not be accepted. The line must be a value in the range 1 to
  447.      ListMaxHeaders (which defaults to 4).
  448.  
  449.      ListAssignFooter(var ListDetails: ListCfg; Line:byte; var
  450.                                                        Footnote:string);
  451.  
  452.           Sets the list configuration variable to display a string as a
  453.      footer. A string variable must be passed -- a string literal will
  454.      not be accepted. The line must be a value in the range 1 to
  455.      ListMaxFooters (which defaults to 4).
  456.  
  457.      ListSetHeaderOff(var ListDetails: ListCfg; Line:byte);
  458.  
  459.           Removes a header line which was previously assigned with
  460.      ListAssignHeader.
  461.  
  462.      ListSetFooterOff(var ListDetails: ListCfg; Line:byte);
  463.  
  464.           Removes a header line which was previously assigned with
  465.      ListAssignFooter.
  466.  
  467.      ListScrollHeader(var ListDetails: ListCfg; On:boolean);
  468.  
  469.           Pass TRUE if the headings should be scrolled right and left
  470.      when the user scrolls the list body right and left, or FALSE if the
  471.      header should remain fixed.
  472.  
  473.      ListScrollFooter(var ListDetails: ListCfg; On:boolean);
  474.  
  475.           Pass TRUE if the headings should be scrolled right and left
  476.      when the user scrolls the list body right and left, or FALSE if the
  477.      header should remain fixed.
  478.  
  479.           You can automatically canter a header or footer by prefixing
  480.      the string with the ^ character.
  481.  
  482.           The following code is an extract from the demo file DEMLS5.PAS
  483.      which shows how to add headers and footers to a list window:
  484.  
  485.           InitListCfg(Settings);
  486.           ListAssignDLL(Settings,DLL);
  487.           ListSetWin(Settings,1,2,80,24,1);
  488.           ListSetTwoColors(Settings,True);
  489.           Header1 := 'This is a header';
  490.           Header2 := 'This is a second header';
  491.           Footer := 'This is a footer';
  492.           ListAssignHeader(Settings,1,Header1);
  493.           ListAssignHeader(Settings,2,Header2);
  494.           ListAssignFooter(Settings,1,Footer);
  495.           CursorOff;
  496.           RunBrowse(Settings,' Browsing '+FileName);
  497.           CursorOn;
  498.  
  499.           Refer to the section Displaying Grid Windows for more
  500.      information on setting headers from grid windows.
  501.  
  502. Displaying Browse Windows
  503.  
  504.           Browse windows are designed for displaying lists without a
  505.      highlight bar. Browse windows are ideal for displaying the contents
  506.      of text files, and displaying help text.
  507.  
  508. Browsing Files
  509.  
  510.           Normally, to display a browse window, you must create a
  511.      ListCfg variable, set this variable as desired using the functions
  512.      described in the last section, and populate a data variable.
  513.      However, if you want to display the contents of a file, you can
  514.      skip this whole process or just call the following procedure:
  515.  
  516.      RunBrowseFile(Fname:PathStr;Tit:StrScreen);
  517.  
  518.           Displays the specified file in a list window with the
  519.      specified title.
  520.  
  521.           If the file cannot be displayed, Gold sets an error in
  522.      GOLDLIST. Always call LastListError to check whether the call to
  523.      RunBrowseFile was successful.
  524.  
  525.      Run the demo file DEMBRS1.PAS to see RunBrowseFile in action.
  526.  
  527.           The RunBrowseFile procedure provides a quick and dirty way to
  528.      browse a file. You can set the window dimensions prior to calling
  529.      the display procedure by accessing the ListVars elements WX1, WY1,
  530.      WX2, WY2, and WinStyle. If you want more control over the display
  531.      format, you should create a ListCfg variable, populate a DLL or SLL
  532.      with the file contents, and use the RunBrowse procedure discussed
  533.      below. The demo file DEMBRS2.PAS illustrates this technique.
  534.  
  535. General Browsing
  536.  
  537.           You can browse the contents of a string array, a single linked
  538.      list, a double linked list or a custom data source. To do so, you
  539.      must create a variable of type ListCfg, initialize the variable
  540.      with InitListCfg and then set the variable using the Listxxx
  541.      functions described in the last few sections. (If you have been
  542.      User Guide surfing and are reading this section without reading the
  543.      earlier material in this chapter, catch a wave to the beginning of
  544.      the chapter!)
  545.  
  546.           Having set the ListCfg variable to meet your needs, just call
  547.      RunBrowse as follows:
  548.  
  549.      RunBrowse(var ListDetails: ListCfg;Tit:StrScreen);
  550.  
  551.      Displays the data identified in ListDetails in a browse window.
  552.  
  553.  
  554.           Listed below is an extract from DEMBRS3.PAS which displays the
  555.      contents of an SLL in a window:
  556.  
  557.         InitSLLStr(SLL);
  558.         SLLSetActiveList(SLL);
  559.         PopulateTheList;
  560.         InitListCfg(Settings);
  561.         ListAssignSLL(Settings,SLL);
  562.         ListSetWin(Settings,28,3,52,22,1);
  563.         CursorOff;
  564.         RunBrowse(Settings,' Browsing ');
  565.         SLLDestroy;
  566.         ResetStartUpMode;
  567.  
  568.  
  569. Displaying List Windows
  570.  
  571.           Having read this far (you did read this far, right?), you know
  572.      all there is to know about displaying lists in a window. To recap,
  573.      initialize a ListCfg variable, assign a data source, and call
  574.      RunList as follows:
  575.  
  576.      RunList(var ListDetails: ListCfg;Tit:StrScreen);
  577.  
  578.           Displays the data identified in ListDetails in a list window.
  579.  
  580.           Back on page 15-3 there is a listing of DEMLS1.PAS which shows
  581.      how easy it is to create and display a list.
  582.  
  583. Determining the Highlighted Pick
  584.  
  585.           The ListCfg variable includes the field ActiveNode, which is
  586.      of type longint. This variable always reflects the number of the
  587.      node which contains the highlight bar.
  588.  
  589. Controlling List Display Characters and Hotkeys
  590.  
  591.           The ListVars variable includes the following three fields
  592.      which control characters used to indicate the higlighted pick
  593.      (ListLeft and ListRight) and tagged items (ListTag):
  594.  
  595.            ListLeft: string[1];
  596.            ListRight: string[1];
  597.            ListTag: string[1];
  598.  
  599.           You can customize the appearance of the list by assigning new
  600.      characters to these variables.
  601.  
  602.           The keystrokes which control item tagging are stored in the
  603.      following ListVars variables:
  604.  
  605.            ToggleKey: word;
  606.            TagKey: word;
  607.            UnTagKey: word;
  608.            TagAllKey: word;
  609.            UnTagAllKey: word;
  610.  
  611. Determining the User's Last Action
  612.  
  613.           The ListCfg variable includes the field LastAction of type
  614.      gAction. Gold updates this variable to indicate how the user ended
  615.      the list session. For example, if the user pressed Esc it would be
  616.      set to Escaped.
  617.  
  618. Displaying Grid Windows
  619.  
  620.           A grid window is designed to provide a table or columnar view
  621.      of a record and is ideal for database applications (see figure
  622.      14.1).
  623.  
  624.           In most respects, the way to display a grid, using RunGrid, is
  625.      identical with the way to display a list. A grid, however, needs
  626.      additional information about the columnar aspects of the grid --
  627.      remember that a grid scrolls left and right by column rather than
  628.      by character, and Gold needs to know the logical column widths, or
  629.      tabs.
  630.  
  631.           In the example, when the user presses the right cursor (or
  632.      clicks the mouse on the horizontal scroll bar), the display will
  633.      shift about 10 characters to the right so that the first visible
  634.      column is Street and the second column is City.
  635.  
  636.           You inform Gold of the column widths by creating an array of
  637.      integers to represent the starting character number of each column
  638.      in the width. Figure 14.1 was generated from the demo file
  639.      DEMGRD1.PAS which included the following code to define the column
  640.      widths:
  641.  
  642.           var
  643.              SourceList: SingleLL;
  644.              GridLayout: ListCfg;
  645.              GridHeading: string;
  646.              TabStops: array[1..5] of integer;
  647.  
  648.           begin
  649.              TabStops[1] := 1;
  650.              TabStops[2] := 18;
  651.              TabStops[3] := 39;
  652.              TabStops[4] := 53;
  653.              TabStops[5] := 57;
  654.              ...
  655.              GridAssignTabs(GridLayout,@TabStops,5);
  656.  
  657.           Each element of the integer array identifies the position of
  658.      the starting character of a column. In this example, the first
  659.      column starts at character 1, the second column starts at character
  660.      18, the third column starts at character 39, and so on. When the
  661.      user scrolls rightward from the name column, Gold will display the
  662.      list starting at the 18th character.
  663.  
  664.  
  665.      Figure 14.1
  666.      A Grid Window
  667.  
  668.  
  669.           Having assigned each integer element of the array with the
  670.      appropriate column setting, the procedure GridAssignTabs is used to
  671.      instruct Gold to use the column (or tab) settings, as follows:
  672.  
  673.      GridAssignTabs(var ListDetails: ListCfg; TA:pGridTabArray;
  674.                                                       Dim:integer);
  675.  
  676.           Sets the ListCfg variable ready for displaying a grid. The
  677.      integer array identifies the starting character of each column. The
  678.      third parameter identifies the total number of elements (i.e.
  679.      columns) defined in the array.
  680.  
  681.      Always set the first integer in the array to a value of 1.
  682.  
  683. Grid Headings and Footers
  684.  
  685.           Grid windows support up to 4 headers and 4 footers, and the
  686.      procedures, ListAssignHeader and ListAssignFooter, are used just
  687.      like list and browse titles. In fact, the use of non-scrolling
  688.      headers and footers behave exactly the same for grid windows as for
  689.      list and browse windows.
  690.  
  691.           Because of a grids columnar scrolling support, however, the
  692.      scrollable titles behave a little differently. Gold needs to know
  693.      the headings (or footers) for each column. Gold searches the
  694.      strings for the split bar character "|" and uses this to separate
  695.      each columns heading. Listed below are the heading statements used
  696.      in generate the headings displayed in figure 14.1:
  697.  
  698.           var
  699.              GridHeading: string;
  700.  
  701.           begin
  702.              ...
  703.              Gridheading := 'Name|Street|City|ST|Zip';
  704.              ListAssignHeader(GridLayout,1,GridHeading);
  705.              ...
  706.           end;
  707.  
  708.           This technique of embedding the column delimiter must be used
  709.      on all header and footer strings which are defined as scrollable.
  710.  
  711.           Review the demo file DEMGRD1.PAS to see columns and headings
  712.      in action.
  713.  
  714. Locking Rows and Columns
  715.  
  716.           One or more columns and one or more rows can be locked so that
  717.      the locked area remains visible as the user scrolls around the
  718.      grid. Use the GridSetLocks procedure to lock columns and rows as
  719.      follows:
  720.  
  721.      GridSetLocks(var ListDetails: ListCfg;LCol,LRow:byte);
  722.  
  723.           Locks columns and rows so that they are always visible. Lcol
  724.      identfies the number of columns (not characters) to lock, and LRow
  725.      identifies the number of rows to lock.
  726.  
  727.           Listed below is an extract from DEMGRD2.PAS which uses the
  728.      column locking facility to keep the name column always visible:
  729.  
  730.           procedure SetGridLayout;
  731.           {}
  732.           begin
  733.              Gridheading := 'Name|Street|City|ST|Zip';
  734.              GridFootnote := 'The name column is locked';
  735.              TabStops[1] := 1;
  736.              TabStops[2] := 18;
  737.              TabStops[3] := 39;
  738.              TabStops[4] := 53;
  739.              TabStops[5] := 57;
  740.              InitListCfg(GridLayout);
  741.              ListAssignSLL(GridLayout,SourceList);
  742.              ListAssignHeader(GridLayout,1,GridHeading);
  743.              ListAssignFooter(GridLayout,1,GridFootnote);
  744.              ListScrollFooter(GridLayout,false);
  745.              ListSetWin(GridLayout,15,5,65,15,7);
  746.              ListSetGaps(GridLayout,1,0,0,1);
  747.              GridAssignTabs(GridLayout,@TabStops,5);
  748.              GridSetLocks(GridLayout,1,0);
  749.           end; { SetGridLayout }
  750.  
  751. Determining the Highlighted Pick
  752.  
  753.           The ListCfg variable includes the field ActiveNode, which is
  754.      of type longint. This variable always reflects the number of the
  755.      node which contains the highlight bar.
  756.  
  757. Controlling Grid Display Characters
  758.  
  759.           The ListVars variable includes the following three fields
  760.      which control characters used to indicate the higlighted pick
  761.      (GridLeft and GridRight) and tagged items (gridTag):
  762.  
  763.         GridLeft: string[1];
  764.         GridRight: string[1];
  765.         GridTag: string[1];
  766.  
  767.           You can customize the appearance of the list by assigning new
  768.      characters to these variables.
  769.  
  770.           The keystrokes which control item tagging are stored in the
  771.      following ListVars variables:
  772.  
  773.            ToggleKey: word;
  774.            TagKey: word;
  775.            UnTagKey: word;
  776.            TagAllKey: word;
  777.            UnTagAllKey: word;
  778.  
  779. Determining the User's Last Action
  780.  
  781.           The ListCfg variable includes the field LastAction of type
  782.      gAction. Gold updates this variable to indicate how the user ended
  783.      the list session. For example, if the user pressed Esc it would be
  784.      set to Escaped.
  785.  
  786. Using a Custom Data Source
  787.  
  788.           In all the examples so far, you have seen how to display lists
  789.      of strings from linked lists or string arrays. You may recall that
  790.      one of the procedures ListAssignArray, ListAssignSLL or
  791.      ListAssignSLL is used to inform Gold about the data source. This
  792.      approach requires all the data to be in memory at once, and for the
  793.      majority of applications, that is not a problem.
  794.  
  795.           There are, however, some situations where there is too much
  796.      data to load into memory at once. You might be trying to list
  797.      10,000 records from a database, for example. For situations such as
  798.      this, Gold allows you to assign a custom list data source using the
  799.      procedure ListAssignCustom which is defined as follows:
  800.  
  801.      ListAssignCustom(var ListDetails: ListCfg; Total:longint;
  802.                                             CustomFunc:ListGetStrFunc);
  803.  
  804.           Sets the ListCfg variable data source as custom. The procedure
  805.      is passed the total number of entries in the custom data source
  806.      along with a function which Gold will call every time it needs a
  807.      string from the custom source.
  808.  
  809.           Every time Gold needs to display a string in a browse, list or
  810.      grid window, the CustomFunc function will be called. For a function
  811.      to be eligible as a custom list function it must adhere to the
  812.      following rules:
  813.  
  814.           The procedure must be declared as a far procedure at the root
  815.           level. Refer to the section Understanding Hooks in Chapter 3
  816.           for further information.
  817.  
  818.           The function  must be declared with four passed parameters.
  819.           The first parameter is a pointer, and the last three
  820.           parameters are longints.
  821.  
  822.      The following procedure declaration follows these rules:
  823.  
  824.           {$F+}
  825.           function GetStrfromDB(P:pointer; Element,Start,Finish:
  826.                                                       longint): string;
  827.           {}
  828.           begin
  829.            ....
  830.           end; { GetStrfromDB }
  831.           {$F-}
  832.  
  833.           When the procedure is called Gold actually passes a pointer to
  834.      the ListCfg variable as the first parameter. In most situations you
  835.      will not need to take advantage of this parameter. The second
  836.      parameter is the node or item number for which Gold needs the
  837.      string. The third and fourth parameters represent the starting and
  838.      ending character positions of the (sub) string which will be
  839.      visible.
  840.  
  841.           In the case of a database list, the custom function would load
  842.      the database record, access the data in the fields, and then return
  843.      the requested sub-string. Review the demo file DEMGRD3.PAS to see
  844.      this technique in action.
  845.  
  846. Using Hooks to Fine Tune Lists
  847.  
  848.           Even with all this flexibility built into the list facility,
  849.      there may still be occasions when you want to add some custom
  850.      functionality. As always, Gold has a set of hooks where you can
  851.      fine tune the behavior of the application.
  852.  
  853.           Gold provides four different hooks for customizing browse,
  854.      list and grid windows.
  855.  
  856. The Character Hook
  857.  
  858.           A character hook is a procedure which is called every time a
  859.      key is pressed or a mouse button is clicked while a list window has
  860.      focus. The hooked procedure is called before the key is processed
  861.      by Gold. The hook is particularly useful for trapping special keys
  862.      like F1 for help, or Alt-S to search.
  863.  
  864.           All you have to do is create a procedure following some
  865.      specific rules, and then call the ListAssignCharHook procedure to
  866.      instruct Gold to call your procedure every time a key is pressed.
  867.  
  868.           For a procedure to be eligible as a character hook it must
  869.      adhere to the following rules:
  870.  
  871.           The procedure must be declared as a far procedure at the root
  872.           level. Refer to the section Understanding Hooks in Chapter 3
  873.           for further information.
  874.  
  875.           The procedure must be declared with one variable parameter of
  876.           type word, and two variable parameters of type byte. These
  877.           parameters identify the user input, i.e. the Key, X and Y.
  878.  
  879.      The following procedure declaration follows these rules:
  880.  
  881.           {$F+}
  882.           procedure MyCharHook(var Code:word;var X,Y:byte);
  883.           begin
  884.              {some code}
  885.           end; {MyCharHook}
  886.           {$F-}
  887.  
  888.           The following procedure is then called to instruct Gold to
  889.      call your procedure after each input:
  890.  
  891.      ListAssignCharHook(var ListDetails: ListCfg; Proc:KeyPressedHook);
  892.  
  893.           Instructs Gold to call the specified procedure before
  894.      processing each user input to a list window.
  895.  
  896.           If, subsequently, you want to remove the character hook,
  897.      execute the following procedure:
  898.  
  899.      ListRemoveCharHook(var ListDetails:ListCfg);
  900.  
  901.           Removes a list character which was previously assigned with
  902.      ListAssignCharHook.
  903.  
  904. The Hind Hook
  905.  
  906.           A list hind hook is similar to a character hook, except the
  907.      hook is called after an input has been processed by Gold. If you
  908.      want to write some additional information to the screen based on
  909.      the active list item, you should take advantage of the hind hook.
  910.  
  911.           For a procedure to be eligible as a hind hook it must adhere
  912.      to the following rules:
  913.  
  914.           The procedure must be declared as a far procedure at the root
  915.           level. Refer to the section Understanding Hooks in Chapter 3
  916.           for further information.
  917.  
  918.           The procedure must be declared with one parameter of type
  919.           ListCfgPtr.
  920.  
  921.      The following procedure declaration follows these rules:
  922.  
  923.           {$F+}
  924.           procedure MyHineyHook(ListDetailsPtr:ListCfgPtr);
  925.           begin
  926.              {some code}
  927.           end; {MyHineyHook}
  928.           {$F-}
  929.  
  930.           The following procedure is then called to instruct Gold to
  931.      call your procedure after each input:
  932.  
  933.      ListAssignHindHook(var ListDetails: ListCfg; Proc:ListHindHook);
  934.  
  935.           Instructs Gold to call the specified procedure after
  936.      processing each user input to a list window, and once when the
  937.      window is first displayed.
  938.  
  939.           The variable parameter which is passed to the procedure is
  940.      actually a pointer to the ListCfg variable which is being used by
  941.      the list. You can de-reference the pointer to access the variable,
  942.      for example:
  943.  
  944.           Total := ListDetails^.TotalNodes
  945.  
  946.           If, subsequently, you want to remove the hind hook, execute
  947.      the following procedure:
  948.  
  949.      ListRemoveHindHook(var ListDetails:ListCfg);
  950.  
  951.           Removes a list hind which was previously assigned with
  952.      ListAssignHindHook.
  953.  
  954. The Color Hook
  955.  
  956.           The color hook provides a really easy way to go beyond the
  957.      standard two colors supported by the primary list code. For
  958.      example, you might want every tenth item in a list to be displayed
  959.      in a different color, or all items with a quantity field greater
  960.      than 5000 to be displayed in a different color.
  961.  
  962.           A color hook is called every time Gold wants to display a line
  963.      of text in a browse, list or grid window. For a procedure to be
  964.      eligible as a color hook it must adhere to the following rules:
  965.  
  966.           The procedure must be declared as a far procedure at the root
  967.           level. Refer to the section Understanding Hooks in Chapter 3
  968.           for further information.
  969.  
  970.           The procedure must be declared with three parameters. The
  971.           first parameter is a longint which indicates the node or item
  972.           number of the item that is about to be written to the window.
  973.           The second parameter is a boolean which will be set to TRUE if
  974.           the pick is the highlighted pick. The third parameter is a
  975.           variable parameter of type byte which represents the default
  976.           color that will be used -- this parameter should be updated by
  977.           the hook if a custom color is to be used.
  978.  
  979.      The following procedure declaration follows these rules:
  980.  
  981.           {$F+}
  982.           procedure MyColorHook(Pick:longint;Hi:boolean;
  983.                                                      var Attr:byte);
  984.           begin
  985.              {some code}
  986.           end; {MyColorHook}
  987.           {$F-}
  988.  
  989.           The following procedure is then called to instruct Gold to
  990.      call your procedure after each input:
  991.  
  992.      ListAssignColorHook(var ListDetails: ListCfg; Proc:ListColorHook);
  993.  
  994.           Instructs Gold to call the specified procedure before writing
  995.      the item to the list window. The hook can modify the item's display
  996.      color.
  997.  
  998.           If, subsequently, you want to remove the color hook, execute
  999.      the following procedure:
  1000.  
  1001.      ListRemoveColorHook(var ListDetails:ListCfg);
  1002.  
  1003.           Removes a list color which was previously assigned with
  1004.      ListAssignSelectHook.
  1005.  
  1006. The Selection Hook
  1007.  
  1008.           A selection hook is called every time the user takes an action
  1009.      which might be construed as the conclusion of the list session.
  1010.      Specifically, a list selection hook is called when the user clicks
  1011.      on the close icon, double clicks on a list item, presses Esc or
  1012.      presses Enter.
  1013.  
  1014.           By default, Gold will end the input session and close the list
  1015.      window when any of these actions are taken by the user. In some
  1016.      situations, however, you may want to override this default behavior
  1017.      using a selection hook.
  1018.  
  1019.           For a procedure to be eligible as a list selection hook it
  1020.      must adhere to the following rules:
  1021.  
  1022.           The procedure must be declared as a far procedure at the root
  1023.           level. Refer to the section Understanding Hooks in Chapter 3
  1024.           for further information.
  1025.  
  1026.           The procedure must be declared with one parameter of type
  1027.           ListCfgPtr.
  1028.  
  1029.      The following procedure declaration follows these rules:
  1030.  
  1031.           {$F+}
  1032.           function MySelectHook(var Listdetails):gAction;begin
  1033.              {some code}
  1034.           end; {MySelectHook}
  1035.           {$F-}
  1036.  
  1037.           The following procedure is then called to instruct Gold to
  1038.      call your procedure after each input:
  1039.  
  1040.      ListAssignSelectHook(var ListDetails: ListCfg;
  1041.                                                 Proc:ListSelectHook);
  1042.  
  1043.           Instructs Gold to call the specified procedure when the user
  1044.      selects a list item by pressing Enter or double clicking on the
  1045.      item, or when the user tries to escape by pressing Esc or clicking
  1046.      on the window's close icon.
  1047.  
  1048.           The variable parameter which is passed to the procedure is
  1049.      actually a pointer to the ListCfg variable which is being used by
  1050.      the list. You can dereference the pointer to access the variable,
  1051.      for example:
  1052.  
  1053.           Total := ListDetails^.TotalNodes
  1054.  
  1055.           The function returns a value of type gAction (declared in
  1056.      GOLDIO) which indicates how Gold should proceed. For example, an
  1057.      action code of Refresh will instruct Gold to repaint the window's
  1058.      client area, and an action code of Finished will instruct Gold to
  1059.      close the list window.
  1060.  
  1061.           If, subsequently, you want to remove the select hook, execute
  1062.      the following procedure:
  1063.  
  1064.      ListRemoveSelectHook(var ListDetails:ListCfg);
  1065.  
  1066.           Removes a list selection hook which was previously assigned
  1067.      with ListAssignSelectHook, and instructs Gold to use the default
  1068.      hook.
  1069.  
  1070.  
  1071.           The demo file DEMGRD4.PAS takes advantage of the selection
  1072.      hook to add a record editor to a database browser. Check it out!
  1073.  
  1074. Launching Windows on the Desktop
  1075.  
  1076.           The three primary functions RunBrowse, RunList and RunGrid
  1077.      have the following counterparts for displaying windows on a desktop
  1078.      application:
  1079.  
  1080.      LaunchBrowse(var ListDetails: ListCfg;Tit:StrScreen;
  1081.                                           CloseProc:ListCloseProc):byte;
  1082.  
  1083.           Launches a browser for viewing the contents of an array or
  1084.      linked list. The function returns the number (or handle) of the
  1085.      newly created window.
  1086.  
  1087.      LaunchList(var ListDetails: ListCfg;Tit:StrScreen;
  1088.                                          CloseProc:ListCloseProc): byte;
  1089.  
  1090.           Adds a list window to the desktop. The function returns the
  1091.      number (or handle) of the newly created window.
  1092.  
  1093.      LaunchGrid(var ListDetails: ListCfg;Tit:StrScreen;
  1094.                                          CloseProc:ListCloseProc): byte;
  1095.  
  1096.           Adds a grid window to the desktop. The function returns the
  1097.      number (or handle) of the newly created window.
  1098.  
  1099.           Like their Run counterparts, the Launch functions are passed a
  1100.      ListCfg variable and a title. Additionally, the Launch functions
  1101.      are passed a close function as a third parameter. This close
  1102.      function is called whenever the user tries to close the window on
  1103.      the desktop, and it provides you with an opportunity to do any
  1104.      housekeeping (such as disposing of linked lists) before the window
  1105.      is closed.
  1106.  
  1107.           For a function to be eligible as a list close hook it must
  1108.      adhere to the following rules:
  1109.  
  1110.           The function must be declared as a far function at the root
  1111.           level. Refer to the section Understanding Hooks in Chapter 3
  1112.           for further information.
  1113.  
  1114.           The function must be declared with one parameter of type
  1115.           ListCfgPtr, and one integer. The function must return a
  1116.           boolean value.
  1117.  
  1118.      The following procedure declaration follows these rules:
  1119.  
  1120.           {$F+}
  1121.           function GoodbyeList(var LDP: ListCfgPtr; Handle:integer):
  1122.                                                               boolean;
  1123.           {}
  1124.           begin
  1125.              PopUpSetActive(ListMenu,201,true);
  1126.              SLLDestroy;
  1127.              GoodbyeList := true;
  1128.           end; { GoodbyeList }
  1129.           {$F-}
  1130.  
  1131.           If the function returns false, the window will not be closed.
  1132.      The first parameter passed to the function is a pointer to the
  1133.      ListCfg variable used to display the list. You can dereference this
  1134.      pointer to access the variable, for example:
  1135.  
  1136.           Total := ListDetails^.ActiveNode
  1137.  
  1138.      The demo file DEMDESK5.PAS shows the LaunchList function in action.
  1139.  
  1140. Handling Errors
  1141.  
  1142.           The list displaying functions and the header and footer
  1143.      assignment functions have the potential to fail. Be sure to check
  1144.      the error code by calling the LastListError and LastGridError
  1145.      functions.
  1146.  
  1147.